package com.mata.worktime.controller.statistics;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mata.worktime.entity.BaseEntity;
import com.mata.worktime.entity.user.Role;
import com.mata.worktime.entity.user.User;
import com.mata.worktime.entity.work.Project;
import com.mata.worktime.entity.work.WorkHour;
import com.mata.worktime.service.user.DeptService;
import com.mata.worktime.service.user.RoleService;
import com.mata.worktime.service.work.ProjectService;
import com.mata.worktime.vo.LayuiTableVO;
import com.mata.worktime.vo.statistics.ProjectDetailVO;
import com.mata.worktime.vo.statistics.ProjectStatisicsVO;
import com.mata.worktime.vo.statistics.UserDetailVO;
import com.mata.worktime.vo.statistics.UserStatisicsVO;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import com.mata.worktime.controller.BaseController;
import com.mata.worktime.dto.PageParamDTO;
import com.mata.worktime.dto.ProjectStatisticsParamDTO;
import com.mata.worktime.dto.UserStatisticsParamDTO;
import com.mata.worktime.dto.WeekDTO;
import com.mata.worktime.entity.work.ProjectType;
import com.mata.worktime.service.statistics.StatisticsService;
import com.mata.worktime.service.work.ProjectTypeService;
import com.mata.worktime.util.ExcelStyleUtil;
import com.mata.worktime.util.ExcelUtil;
import com.mata.worktime.util.WeekUtils;

import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparingLong;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;


/**
 * 统计
 *
 * @author earthchen
 * @date 2018/10/16
 **/
@RequestMapping("/statistics")
@Controller
public class StatisticsController extends BaseController
{
    @Autowired
    private RoleService roleService;

    @Autowired
    private StatisticsService statisticsService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private ProjectTypeService projectTypeService;

    @Autowired
    private DeptService deptService;

    private Logger logger = LoggerFactory.getLogger(StatisticsController.class);

    /**
     * 项目工时统计页
     *
     * @return 项目工时统计页
     */
    @RequiresPermissions("statistics:project:view")
    @GetMapping("/project/view")
    public String project(Model model)
    {
        List<ProjectType> projectTypeList = projectTypeService.list(new QueryWrapper<>());
        model.addAttribute("typeList", projectTypeList);
        return "tongji/xmgs_tongji";
    }

    /*
     * @description 跳转到项目每日统计
     * @author CamphorWood
     * @date 2021/4/7 16:28
     * @param model
     * @return java.lang.String
     */
    @RequiresPermissions("statistics:project:view")
    @GetMapping("/project/daily")
    public String daily(Model model)
    {
        List<Long> proIds = new ArrayList<>();
        QueryWrapper<Project> eq = new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0").orderByDesc("start_date");
        int isLeader = isLeader();
        // 如果角色中含有管理员
        if (isLeader >= 4) {
            model.addAttribute("projectList", projectService.list(eq));
            return "tongji/dailyStatistics";
        }
        getProIds(proIds, isLeader);//获取所属角色下的项目id
        if (proIds.size() > 0) {
            eq.in("id", proIds);
        }
        List<Project> projectList = projectService.list(eq);
//        List<ProjectType> projectTypeList = projectTypeService.list(new QueryWrapper<>());
        model.addAttribute("projectList", projectList);
//        model.addAttribute("typeList", projectTypeList);
        return "tongji/dailyStatistics";
    }
    /**
     * 项目工时详情
     *
     * @param model     模型
     * @param projectId 项目编号
     * @return 详情页
     */
    @RequiresPermissions("statistics:project:detailview")
    @GetMapping("/project/view/{projectId}")
    public String projectDetail(Model model, @PathVariable("projectId") String projectId,
                                String projectName,
                                Date startDate,
                                Date endDate)
    {
        model.addAttribute("projectName",projectName);
        model.addAttribute("projectId", projectId);
        model.addAttribute("startDate", startDate);
        model.addAttribute("endDate", endDate);
        return "tongji/detail/projectDetail";
    }

    /**
     * 分页获取项目工时统计
     *
     * @param dto          项目统计查询参数
     * @param pageParamDTO 分页参数
     * @return 项目统计信息的 layui table
     */
    @RequiresPermissions("statistics:project:list")
    @GetMapping("/project/list")
    @ResponseBody
    public LayuiTableVO<ProjectStatisicsVO> projectData(ProjectStatisticsParamDTO dto,
                                                        PageParamDTO pageParamDTO)
    {
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        int leader = isLeader();

        if(leader == 1){
            // 存储获取的项目id
            List<Long> projectIds = new ArrayList<>();
            //只是项目经理 获取所属的项目列表
            List<Project> projects = projectService.list(new QueryWrapper<Project>().eq("manager", getUserId().toString()));
            if(projects.size() != 0) {
                for (Project project : projects) {
                    projectIds.add(project.getId());
                }
            }
            if(projectIds.size()>0){
                dto.setProjectIds(projectIds);
            }
        }

        if(leader == 2){
            // 获取部门下的部门id
            List<Long> deptIdList = new ArrayList<>();
            //只是部门经理
            deptService.getAllChildrenDept(getUser().getDeptId()).forEach(dept -> deptIdList.add(dept.getId()));
            if(deptIdList.size()>0){
                dto.setDeptIds(deptIdList);
            }
        }

        if(leader == 3){
            // 获取的项目id
            List<Long> projectIds = new ArrayList<>();
            // 获取部门下的部门id
            List<Long> deptIdList = new ArrayList<>();
            //获取项目经理的项目id
            projectService.list(new QueryWrapper<Project>().eq("manager", getUserId().toString())).forEach(project -> projectIds.add(project.getId()));

            //只是部门经理
            deptService.getAllChildrenDept(getUser().getDeptId()).forEach(dept -> deptIdList.add(dept.getId()));
            // 获取部门下的项目id
            projectService.list(new QueryWrapper<Project>().in("dept_id", deptIdList)).forEach(project -> projectIds.add(project.getId()));


            if(projectIds.size()>0){
                dto.setProjectIds(projectIds.stream().distinct().collect(Collectors.toList()));
            }
        }


        IPage<ProjectStatisicsVO> projectStatisicsVOS = statisticsService.projectStatistics(dto, pageParamDTO);
        return getTableInfo(projectStatisicsVOS);
    }

    // 根据角色不同获取不同数据
    private int isLeader() {
        // 是否项目经理的标志
        int isLeader = 0;
        List<Role> roles = roleService.selectRolesByUserId(getUserId());
        for (Role role : roles) {
            if (role.isFlag()) {
                if (role.getRoleName().equals("项目经理")) {
                    isLeader += 1;
                }
                if (role.getRoleName().equals("部门经理")) {
                    isLeader += 2;
                }
                if (role.getRoleName().equals("管理员")) {
                    isLeader += 4;
                }
            }
        }
        return isLeader;
    }

    private List<Long> getProIds(List<Long> proIds, int isLeader) {
        List<Long> deptIdList = new ArrayList<>();
        // 如果是项目经理
        if (isLeader == 1) {
            List<Project> projectList = projectService.list(new QueryWrapper<Project>().eq("status", "0")
                    .eq("del_flag", "0").eq("manager", getUserId().toString()));
            projectList.forEach(project -> proIds.add(project.getId()));
        }
        // 如果是部门经理
        if (isLeader == 2) {
            deptService.getAllChildrenDept(getUser().getDeptId()).forEach(dept -> deptIdList.add(dept.getId()));
            List<Project> projectList = projectService.list(new QueryWrapper<Project>().eq("status", "0")
                    .eq("del_flag", "0").in("dept_id", deptIdList));
            projectList.forEach(project -> proIds.add(project.getId()));
        }
        // 既是项目经理 也是 部门经理
        if (isLeader == 3) {
            deptService.getAllChildrenDept(getUser().getDeptId()).forEach(dept -> deptIdList.add(dept.getId()));
            List<Project> projectList = projectService.list(new QueryWrapper<Project>().eq("status", "0")
                    .eq("del_flag", "0").in("dept_id", deptIdList));
            projectList.forEach(project -> proIds.add(project.getId()));
            List<Project> projectList1 = projectService.list(new QueryWrapper<Project>().eq("status", "0")
                    .eq("del_flag", "0").eq("manager", getUserId().toString()));
            projectList1.forEach(project -> proIds.add(project.getId()));
        }
        return proIds.stream().distinct().collect(Collectors.toList());
    }


    /*
     * @description 分页查询项目总计
     * @author CamphorWood
     * @date 2021/4/7 14:43
     * @param dto  项目统计查询参数
     * @return com.mata.worktime.vo.LayuiTableVO<com.mata.worktime.vo.statistics.ProjectStatisicsVO>
     */
    @RequiresPermissions("statistics:project:list")
    @PostMapping("/project/dailyProject")
    @ResponseBody
    public List<Object> dailyProject(ProjectStatisticsParamDTO dto)
    {
        System.out.println(dto.getProjectId());
        //如果有一个时间为空，设置为本周时间
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        List<Object> list = new ArrayList<>();
        Map map = statisticsService.dailyStatistics(dto);
        for (Object o : map.keySet()) {
            System.out.println("key:" + o + " " + "Value:" + map.get(o));
//            list.add(JSON.toJSONString(map.get(o)));
            list.add(map.get(o));
        }
        return list;
    }



    /**
     * 项目工时导出excel
     *
     * @param dto      项目统计请求参数
     * @param response 响应体
     */
    @RequiresPermissions("statistics:project:excel")
    @GetMapping("/project/excel")
    public void projectDataToExcel(ProjectStatisticsParamDTO dto,
                                   HttpServletResponse response)
    {
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        List<ProjectStatisicsVO> projectStatisicsVOS = statisticsService.projectStatistics(dto);
        ExportParams exportParams = new ExportParams("项目工时统计", "统计", ExcelType.XSSF);
        exportParams.setStyle(ExcelStyleUtil.class);
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams,
            ProjectStatisicsVO.class, projectStatisicsVOS);
        try
        {
            ExcelUtil.export(response, workbook, "项目工时统计.xls");
        }
        catch (Exception e)
        {
            logger.error("excel导出错误");
        }
    }

    /**
     * 项目工时详情
     *
     * @param pageParamDTO 分页参数
     * @param dto          项目请求参数
     * @return 项目详情layui table
     */
    @RequiresPermissions("statistics:project:detail")
    @GetMapping("/project/detail")
    @ResponseBody
    public LayuiTableVO<ProjectDetailVO> projectDetailData(PageParamDTO pageParamDTO,
                                                           ProjectStatisticsParamDTO dto)
    {
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }

        IPage<ProjectDetailVO> projectDetailVOS = statisticsService.projectDetail(dto, pageParamDTO);
        return getTableInfo(projectDetailVOS);
    }

    /**
     * 员工工时统计页
     *
     * @return 员工工时统计页
     */
    @RequiresPermissions("statistics:user:view")
    @GetMapping("/user/view")
    public String user(Model model)
    {
        List<Long> proIds = new ArrayList<>();
        QueryWrapper<Project> eq = new QueryWrapper<Project>()
                .eq("status", "0")
                .eq("del_flag", "0").orderByDesc("start_date");
        int isLeader = isLeader();
        // 如果角色中含有管理员
        if (isLeader >= 4) {
            model.addAttribute("projectList", projectService.list(eq));
            return "tongji/yggs_tongji";
        }
        getProIds(proIds, isLeader);//获取所属角色下的项目id
        if (proIds.size() > 0) {
            eq.in("id", proIds);
        }
        List<Project> projectList = projectService.list(eq);
//        List<ProjectType> projectTypeList = projectTypeService.list(new QueryWrapper<>());
        model.addAttribute("projectList", projectList);
//        model.addAttribute("typeList", projectTypeList);
        return "tongji/yggs_tongji";
    }

    /**
     * 员工工时详情
     *
     * @param model    模型
     * @param username 用户名
     * @return 详情页
     */
    @RequiresPermissions("statistics:user:detailview")
    @GetMapping("/user/view/{username}")
    public String userDetail(Model model, @PathVariable("username") String username,
                             Date startDate, Date endDate)
    {
        model.addAttribute("username", username);
        model.addAttribute("startDate", startDate);
        model.addAttribute("endDate", endDate);
        return "tongji/detail/userDetail";
    }

    /**
     * 员工工时统计
     *
     * @param pageParamDTO 分页参数
     * @param dto          员工统计参数
     * @return 员工统计 layui table
     */
    @RequiresPermissions("statistics:user:list")
    @GetMapping("/user/list")
    @ResponseBody
    public LayuiTableVO<UserStatisicsVO> userData(PageParamDTO pageParamDTO,
                                                  UserStatisticsParamDTO dto)
    {

        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        IPage<UserStatisicsVO> statisicsVOS = statisticsService.userStatistics(dto, pageParamDTO);
        return getTableInfo(statisicsVOS);
    }

    /**
     * 员工工时导出excel
     *
     * @param dto      员工统计参数
     * @param response 响应
     */
    @RequiresPermissions("statistics:user:excel")
    @GetMapping("/user/excel")
    public void userDataToExcel(UserStatisticsParamDTO dto,
                                HttpServletResponse response)
    {
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        List<UserStatisicsVO> statisicsVOS = statisticsService.userStatistics(dto);
        statisicsVOS.forEach(item -> {
            item.setStartDate(DateFormatUtils.format(dto.getStartDate(), "yyyy-MM-dd"));
            item.setEndDate(DateFormatUtils.format(dto.getEndDate(), "yyyy-MM-dd"));}
        );
//        System.out.println("开始时间"+ DateFormatUtils.format(dto.getStartDate(), "yyyy-MM-dd"));
//        System.out.println("结束时间"+DateFormatUtils.format(dto.getEndDate(), "yyyy-MM-dd"));
//        System.out.println("结果集"+statisicsVOS);
        ExportParams exportParams = new ExportParams("员工工时统计", "统计", ExcelType.XSSF);
        exportParams.setStyle(ExcelStyleUtil.class);
        Workbook workbook = ExcelExportUtil.exportExcel(exportParams,
            UserStatisicsVO.class, statisicsVOS);
        try
        {
            ExcelUtil.export(response, workbook, "员工工时统计");
        }
        catch (Exception e)
        {
            logger.error("excel导出错误");
        }
    }

    /**
     * 员工工时详情
     *
     * @param pageParamDTO 分页参数
     * @param dto          员工统计请求参数
     * @return 员工工时详情 layui table
     */
    @RequiresPermissions("statistics:user:detail")
    @GetMapping("/user/detail")
    @ResponseBody
    public LayuiTableVO<UserDetailVO> userDetailData(PageParamDTO pageParamDTO,
                                                     UserStatisticsParamDTO dto)
    {
        if (dto.getStartDate() == null || dto.getEndDate() == null)
        {
            WeekDTO weekDTO = WeekUtils.getWeekDays(0);
            dto.setStartDate(weekDTO.getStartDate());
            dto.setEndDate(weekDTO.getEndDate());
        }
        IPage<UserDetailVO> userDetailVOS = statisticsService.userDetail(dto, pageParamDTO);
        return getTableInfo(userDetailVOS);
    }
}
